/*******************************************************************
 *
 * Copyright (C), 2021-2022, LS, All rights reserved.
 *
 * Author      : 
 * Create Time : 2020-12-15
 * Version     : v0.1
 * Description : 
 *******************************************************************/
 
/*----------------------------Head file----------------------------*/
#include "string.h"
#include "bsp_hw_config.h"
#include "ls_ble_adpter.h"
#include "ls_ble_sdk_config.h"
#include "ls_ble_file_img_api.h"
#include "ls_ble_file_protocol.h"
#include "disp_img_config.h"

#if (LS_BLE_FILE_SVC_ENABLE)

#define BLE_FILE_IMG_LOG_EN  1
#if BLE_FILE_IMG_LOG_EN
#include "ls_ble_log.h"
#define TAG                             "ble_file_img"
#define BLE_FILE_IMG_LOG(level, ...)    LS_BLE_LOG_PRINT(level, TAG, __VA_ARGS__)
#else
#define BLE_FILE_IMG_LOG(...)
#endif

/*----------------------------macro file---------------------------*/
#define file_img_flash_erase_sector(addr)    ls_ble_adpter_flash_erase_sector(addr)
#define file_img_flash_write				 ls_ble_adpter_flash_write
#define file_img_flash_read                  ls_ble_adpter_flash_read

#define file_img_wdt_feed                    ls_ble_adpter_wdt_feed

/*----------------------------type define--------------------------*/

/*----------------------------var define---------------------------*/							
static img_file_info_t img_file_info;

/*-------------------------func declaration------------------------*/

/*-----------------------------------------------------------------*/

void file_img_flash_area_erase(uint32_t bin_size)
{
    if(bin_size <= 0 || bin_size > DISP_IMG_MAX_SIZE)    //Prevent device firmware get damaged.
        return;
    
    uint16_t erase_sector_num = (bin_size / LS_BLE_FLASH_SECTOR_SIZE);
    
    if(bin_size < (DISP_IMG_MAX_SIZE - LS_BLE_FLASH_SECTOR_SIZE)) {
        erase_sector_num += 1;
    }
    LS_BLE_LOG_RAW_INFO("erase_sector_num: %d.", erase_sector_num);
    
    for(uint16_t i=0;i<erase_sector_num;i++) {
		file_img_flash_erase_sector(DISP_IMG_START_ADDR + i*LS_BLE_FLASH_SECTOR_SIZE);
        file_img_wdt_feed();
	}
}


bool file_disp_image_check_crc_valid(void)
{
    uint16_t crc = 0;
    uint32_t offset = 0;
    uint8_t buf[128];
    uint16_t len = 0;
    uint32_t left_size = img_file_info.file_len;

    while(left_size > 0) {
        if(left_size > sizeof(buf)) {
            len = sizeof(buf);
        }
        else {
            len = left_size;
        }
        file_img_flash_read(DISP_IMG_START_ADDR + offset, buf, len);
        left_size -= len;
        offset += len;
        for(int j=0;j<len;j++) {
            crc += buf[j];
        }
    }

    LS_BLE_LOG_RAW_INFO("CalcCRC=%x, ImgCRC=%x\r\n", crc, img_file_info.file_crc16);
    if(crc != img_file_info.file_crc16) {
        return false;
    }

    return true;
}


uint8_t ls_ble_file_set_img_info(uint8_t *payload, uint16_t payload_len, file_trans_t* file_trans)
{
    if(payload_len < sizeof(img_file_info_t)) {
        LS_BLE_LOG_RAW_INFO("payload_len err.\n");
        return IMG_INFO_TYPE_ERROR;
    }
    
    img_file_info_t* info = (img_file_info_t*)payload;
    
    if(info->file_len <= 0 || info->file_len > DISP_IMG_MAX_SIZE) {
        LS_BLE_LOG_RAW_INFO("Err file_len: %d.\n", info->file_len);
        return IMG_INFO_SIZE_ERROR;
    }
    
    if(DEVICE_TYPE != info->dev_type) {
        LS_BLE_LOG_RAW_INFO("Err dev_type: %d.\n", info->dev_type);
        return IMG_INFO_DEV_TYPE_ERR;
    }
    
    if(PROJECT_NUM != info->project_num) {
        LS_BLE_LOG_RAW_INFO("Err project_num: %d.\n", info->project_num);
        return IMG_INFO_PROJ_NUM_ERR;
    }
    
    if(UI_LIB_MAJOR_VER != info->major_version) {
        LS_BLE_LOG_RAW_INFO("Err ver %d.%d: %d.\n", info->major_version, info->minor_version);
        return IMG_INFO_VERSION_ERR;
    }
    
    memset(&img_file_info, 0, sizeof(img_file_info));
    memcpy(&img_file_info, (uint8_t*)info, sizeof(img_file_info));
    
    LS_BLE_LOG_RAW_INFO("file_len: %d.\n", img_file_info.file_len);
    LS_BLE_LOG_RAW_INFO("dev_type: %d.\n", img_file_info.dev_type);
    LS_BLE_LOG_RAW_INFO("file_crc16: %d.\n", img_file_info.file_crc16);
    LS_BLE_LOG_RAW_INFO("project_num: %d.\n", img_file_info.project_num);
    LS_BLE_LOG_RAW_INFO("major_ver: %d.\n", img_file_info.major_version);
    LS_BLE_LOG_RAW_INFO("minor_ver: %d.\n", img_file_info.minor_version);
    
    file_trans->running = true;
    file_trans->offset = 0;
    file_trans->file_type = FILE_TYPE_IMG;
    file_img_flash_area_erase(img_file_info.file_len);
    
    return 0;
}


void ls_ble_file_img_rx_raw_data_handle(uint8_t *data, uint16_t data_len, file_trans_t* file_trans)
{
    if(FILE_TYPE_IMG != file_trans->file_type)
        return;
    
    file_img_flash_write(DISP_IMG_START_ADDR + file_trans->offset, data, data_len);
    file_trans->offset += data_len;
    //LS_BLE_LOG_RAW_INFO("offset: %d\n", file_trans->offset);
}


uint8_t ls_ble_file_img_trans_done_handle(file_trans_t* file_trans)
{
    if(FILE_TYPE_IMG != file_trans->file_type)
        return 0xFF;

    if(img_file_info.file_len != file_trans->offset)
        return FILE_DONE_SIZE_ERR;
    
    uint8_t try = 0;
    for(try=0;try<3;try++) {
        if(true == file_disp_image_check_crc_valid())
            break;
    }
    if(try >= 3) {
        LS_BLE_LOG_RAW_INFO("file img crc check fail");
        return FILE_DONE_CRC_ERR;
    }
    
    LS_BLE_LOG_RAW_INFO("FILE_DONE_SUCCESS");
    return FILE_DONE_SUCCESS;
}

#endif
